home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / ab20_archive / datacomm / xpr / xprzmodem-2.51.lzh / xprzmodem2.5 / send.c < prev    next >
C/C++ Source or Header  |  1992-01-30  |  17KB  |  606 lines

  1. /**********************************************************************
  2.  * Send.c: File transmission routines for xprzmodem.library;
  3.  * Original Version 2.10, 12 February 1991, by Rick Huebner.
  4.  * Based closely on Chuck Forsberg's sz.c example ZModem code,
  5.  * but too pervasively modified to even think of detailing the changes.
  6.  * Released to the Public Domain; do as you like with this code.
  7.  *
  8.  * Version 2.50, 15 November 1991, CRC-32 additions by William M. Perkins.
  9.  *
  10.  * Version 2.51 29, January 1992, RX_timout fix by John Tillema
  11.  **********************************************************************/
  12.  
  13. #include <proto/all.h>
  14. #include <exec/types.h>
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "xproto.h"
  19. #include "zmodem.h"
  20. #include "xprzmodem.h"
  21.  
  22. #ifdef DEBUGLOG
  23. extern void *DebugLog;
  24. #endif
  25.  
  26. /**********************************************************
  27.  *    long XProtocolSend(struct XPR_IO *xio)
  28.  *
  29.  * Main file transmission routine; called by comm program
  30.  **********************************************************/
  31. long __saveds __asm XProtocolSend(register __a0 struct XPR_IO *xio)
  32. {
  33.    struct Vars *v;
  34.    short err;
  35.  
  36.    /* Perform common setup and initializations */
  37.    if (! (v = setup(xio)) )
  38.       return XPRS_FAILURE;
  39.  
  40. /*  was 600, set to 300 to fix so it uploads correctly */
  41.    v->Rxtimeout = 300;
  42.    v->Wantfcs32 = TRUE;
  43.    v->Rxflags = 0;
  44.  
  45.    /* Transfer the files */  
  46.    zmputs(v, "rz\r");
  47.    stohdr(v, 0L);
  48.    zshhdr(v, ZRQINIT);
  49.    sendbuf(v);
  50.    if (getzrxinit(v) == ERROR)
  51.       upderr(v, "Upload cancelled or timed out");
  52.    else
  53.       sendbatch(v);
  54.  
  55.    /* Clean up and return */
  56.    if (err = v->Errcnt)
  57.       upderr(v, "One or more files skipped due to errors");
  58.    else
  59.       updmsg(v, "Done.");
  60.    if (v->io.xpr_setserial && v->Oldstatus != -1)
  61.       (*v->io.xpr_setserial)(v->Oldstatus);
  62.    FreeMem(v->Filebuf, v->Filebufmax);
  63.    FreeMem(v, (long) sizeof(struct Vars));
  64.   
  65. #ifdef DEBUGLOG
  66.    if (DebugLog)
  67.    {
  68.       xpr_fclose(&v->io, DebugLog);
  69.       DebugLog = NULL;
  70.       }
  71. #endif
  72.    return (err) ? XPRS_FAILURE : XPRS_SUCCESS;
  73.    }    /* End of long XProtocolSend() */
  74.  
  75. /**********************************************************
  76.  *    short getzrxinit(struct Vars *v)
  77.  *
  78.  * Negotiate with receiver to start a file transfer
  79.  **********************************************************/
  80. short getzrxinit(struct Vars *v)
  81. {
  82.    short n;
  83.  
  84.    for (n = v->ErrorLimit; --n >= 0; )
  85.    {
  86.       /* Check for abort from comm program */
  87.       if (v->io.xpr_chkabort && (*v->io.xpr_chkabort)())
  88.          return ERROR;
  89.       switch (zgethdr(v))
  90.       {
  91.       case ZCHALLENGE:        /* Echo receiver's challenge number */
  92.          stohdr(v, v->Rxpos);
  93.          zshhdr(v, ZACK);
  94.          sendbuf(v);
  95.          continue;
  96.       case ZCOMMAND:          /* They didn't see our ZRQINIT; try again */
  97.          stohdr(v, 0L);
  98.          zshhdr(v, ZRQINIT);
  99.          sendbuf(v);
  100.          continue;
  101.       case ZRINIT:            /* Receiver ready; get transfer parameters */
  102.      v->Rxflags = 0xFF & v->Rxhdr[ZF0];
  103.      v->Txfcs32 = (v->Wantfcs32 && (v->Rxflags & CANFC32));
  104.          v->Rxbuflen = ((USHORT) v->Rxhdr[ZP1] << 8) | v->Rxhdr[ZP0];
  105. #ifdef DEBUGLOG
  106.          mysprintf(v->Msgbuf, "Txfcs32=%ld Rxbuflen=%ld Tframlen=%ld\n",
  107.         (long) v->Txfcs32, (long) v->Rxbuflen, (long) v->Tframlen);
  108.          dlog(v, v->Msgbuf);
  109. #endif
  110.          /* Use shortest of the two side's max frame lengths */
  111.          if (v->Tframlen && (! v->Rxbuflen || v->Tframlen < v->Rxbuflen))
  112.             v->Rxbuflen = v->Tframlen;
  113. #ifdef DEBUGLOG
  114.          mysprintf(v->Msgbuf, "Rxbuflen=%ld\n", (long) v->Rxbuflen);
  115.          dlog(v, v->Msgbuf);
  116. #endif
  117.          return OK;
  118.       case ZCAN:
  119.       case RCDO:
  120.       case TIMEOUT:
  121.          upderr(v, v->Msgbuf);
  122.          return ERROR;
  123.       case ZRQINIT:
  124.          if (v->Rxhdr[ZF0] == ZCOMMAND)
  125.         continue;
  126.          /* fallthrough... */
  127.       default:
  128.          zshhdr(v, ZNAK);
  129.          sendbuf(v);
  130.          continue;
  131.          }
  132.       }
  133.    return ERROR;
  134.    }    /* End of short getzrxinit() */
  135.  
  136. /**********************************************************
  137.  *    void sendbatch(struct Vars *v)
  138.  *
  139.  * Send a batch of files
  140.  **********************************************************/
  141. void sendbatch(struct Vars *v)
  142. {
  143.    UBYTE single, done = FALSE;
  144.    long fstate;
  145.  
  146.    /* If template routines not provided, must be single filename */
  147.    if (! v->io.xpr_ffirst || ! v->io.xpr_fnext)
  148.    {
  149.       single = TRUE;
  150.       strcpy(v->Filename, v->io.xpr_filename);
  151.       /* Else use the template routines to get the first filename */
  152.       }
  153.    else
  154.    {
  155.       single = FALSE;
  156.       fstate = (*v->io.xpr_ffirst)(v->Filename, v->io.xpr_filename);
  157.       if (! fstate)
  158.       {
  159.          upderr(v, "No files match template");
  160.          return;
  161.          }
  162.       }
  163.  
  164.    /* If using templates, keep getting names & sending until done */
  165.    while (! done)
  166.    {
  167.       if (sendone(v) == ERROR)
  168.      return;
  169.       if (single)
  170.      break;
  171.       fstate = (*v->io.xpr_fnext)(fstate, v->Filename, v->io.xpr_filename);
  172.       done = ! fstate;
  173.       }
  174.  
  175.    /* End batch and return; if we never got started, just cancel receiver */
  176.    if (v->Filcnt)
  177.       saybibi(v);
  178.    else
  179.       canit(v);
  180.    }    /* End of void sendbatch() */
  181.  
  182. /**********************************************************
  183.  *    short sendone(struct Vars *v)
  184.  *
  185.  * Send the file named in v->Filename
  186.  **********************************************************/
  187. short sendone(struct Vars *v)
  188. {
  189.    struct SetupVars *sv;
  190.  
  191. #ifdef DEBUGLOG
  192.    mysprintf(v->Msgbuf, "*** Sending %s\n", v->Filename);
  193.    dlog(v, v->Msgbuf);
  194. #endif
  195.  
  196.    /* Display name of file being sent for user */
  197.    v->xpru.xpru_updatemask = XPRU_FILENAME;
  198.    v->xpru.xpru_filename = v->Filename;
  199.    (*v->io.xpr_update)(&v->xpru);
  200.  
  201.    /* Set text/binary mode according to options before opening file */
  202.    set_textmode(v);
  203.  
  204.    /* Open the file, if possible */
  205.    if (! (v->File = bfopen(v, "r")))
  206.    {
  207.       ++v->Errcnt;
  208.       upderr(v, "Can't open file; skipping");
  209.       return OK;      /* pass over it, there may be others */
  210.       }
  211.    ++v->Filcnt;
  212.    getsystime(&v->Starttime);
  213.  
  214.    /* Kick off the file transfer */
  215.    sv = (void *) v->io.xpr_data;
  216.    switch (sendname(v))
  217.    {
  218.    case ERROR:
  219.       ++v->Errcnt;
  220.       return ERROR;
  221.    case OK:
  222.       bfclose(v);
  223.       /* File sent; if option DY, delete file after sending */
  224.       if (*sv->option_d == 'Y' && v->io.xpr_extension >= 2 && v->io.xpr_unlink)
  225.       {
  226.          updmsg(v, "Deleting file after send");
  227.          (*v->io.xpr_unlink)(v->Filename);
  228.          }
  229.       break;
  230.       }
  231.    return OK;
  232.    }    /* End of short sendone() */
  233.  
  234. /**********************************************************
  235.  *    short sendname(struct Vars *v)
  236.  *
  237.  * Build file info block consisting of file name, length,
  238.  * time, and mode
  239.  **********************************************************/
  240. short sendname(struct Vars *v)
  241. {
  242.    struct SetupVars *sv;
  243.    UBYTE *p, *q, buff [32];
  244.  
  245.    /* Initialize comm program transfer status display */
  246.    v->Fsize = (v->io.xpr_finfo) ? (*v->io.xpr_finfo)(v->Filename, 1L) : -1;
  247.    v->xpru.xpru_updatemask = XPRU_PROTOCOL | XPRU_FILESIZE | XPRU_MSG
  248.       | XPRU_BLOCKS | XPRU_ERRORS | XPRU_TIMEOUTS | XPRU_BLOCKCHECK
  249.       | XPRU_BYTES | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE;
  250.    v->xpru.xpru_protocol = "ZModem";
  251.    v->xpru.xpru_filesize = v->Fsize;
  252.    v->xpru.xpru_msg = (v->Lzconv == ZCNL) ? "Sending text file..." :
  253.       ( (v->Lzconv == ZCBIN) ? "Sending binary file..." : "Sending file...");
  254.    v->xpru.xpru_blocks = v->xpru.xpru_errors = v->xpru.xpru_timeouts = 0;
  255.    v->xpru.xpru_blockcheck = v->Crc32t ? "CRC-32" : "CRC-16";
  256.    v->xpru.xpru_bytes = v->Strtpos = 0;
  257.    update_rate(v);
  258.    (*v->io.xpr_update)(&v->xpru);
  259.  
  260.    sv = (void *) v->io.xpr_data;
  261.    if (*sv->option_s == 'Y')
  262.    {
  263.       /* If "SY" option selected, send full path */
  264.       strcpy(v->Pktbuf, v->Filename);
  265.       p = v->Pktbuf + strlen(v->Pktbuf) + 1;
  266.       }
  267.    else
  268.    {
  269.       /* else extract outgoing file name without directory path */
  270.       for (p = v->Filename, q = v->Pktbuf ; *p; ++p, ++q)
  271.          if ((*q = *p) == '/' || *q == ':')
  272.         q = v->Pktbuf - 1;
  273.       *q = '\0';
  274.       p = ++q;
  275.       }
  276.  
  277.    /* Zero out remainder of file info packet */
  278.    memset(p, 0, sizeof(v->Pktbuf) - (p - v->Pktbuf));
  279.  
  280.    /* Store file size, timestamp, and mode in info packet */
  281.    /*
  282.     * XPR spec doesn't provide a way to get the file timestamp or file mode,
  283.     * so we'll just fake it with the current time and a dummy 0.
  284.     */
  285.    stcl_o(buff, getsystime(NULL) + UnixTimeOffset);
  286.    /* amiga.lib mysprintf() can't do %lo format, so we do it the hard way */
  287.    /* Yes, octal; ZModem was originally done on Unix, and they like octal there */
  288.    mysprintf(p, "%ld %s 0", (v->Fsize < 0) ? 0L : v->Fsize,buff);
  289.  
  290.    /* Send filename packet */
  291.    return zsendfile(v, (short) (p - v->Pktbuf + strlen(p) + 1));
  292.    }    /* End of short sendname() */
  293.  
  294. /**********************************************************
  295.  *    short zsendfile(struct Vars *v, short blen)
  296.  *
  297.  * Send the filename packet and see if receiver will accept
  298.  * file
  299.  **********************************************************/
  300. short zsendfile(struct Vars *v, short blen)
  301. {
  302.    short c;
  303.  
  304.    while (TRUE)
  305.    {
  306.       v->Txhdr[ZF0] = v->Lzconv; /* Text or Binary mode; from config string */
  307.       v->Txhdr[ZF1] = LZMANAG;   /* Default file management mode */
  308.       v->Txhdr[ZF2] = LZTRANS;   /* Default file transport mode */
  309.       v->Txhdr[ZF3] = 0;
  310.       zsbhdr(v, ZFILE);
  311.       zsdata(v, blen, ZCRCW);
  312.       sendbuf(v);
  313. again:
  314.       /* Check for abort from comm program */
  315.       if (v->io.xpr_chkabort && (*v->io.xpr_chkabort)())
  316.       {
  317.          bfclose(v);
  318.          return ERROR;
  319.          }
  320.       switch (c = zgethdr(v))
  321.       {
  322.       case ZRINIT:
  323.          goto again;
  324.       case ZCAN:
  325.       case ZCRC:
  326.       case RCDO:
  327.       case TIMEOUT:
  328.       case ZABORT:
  329.       case ZFIN:
  330.          upderr(v, v->Msgbuf);
  331.          return ERROR;
  332.       case ZSKIP:             /* Receiver doesn't want this one */
  333.          upderr(v, "SKIP command received");
  334.          bfclose(v);
  335.          return c;
  336.       case ZRPOS:             /* Receiver wants it; this is starting position */
  337.          bfseek(v, v->Rxpos);
  338.          v->Strtpos = v->Txpos = v->Rxpos;
  339.          if (v->io.xpr_sflush)
  340.         (*v->io.xpr_sflush)();
  341.          v->Modemcount = 0;
  342.          return zsendfdata(v);
  343.          }
  344.       }
  345.    }    /* End of short zsendfile() */
  346.  
  347. /**********************************************************
  348.  *    short zsendfdata(struct Vars *v)
  349.  *
  350.  * Send the file data
  351.  **********************************************************/
  352. short zsendfdata(struct Vars *v)
  353. {
  354.    short c, e, blklen, goodbytes = 0;
  355.    USHORT framelen, maxblklen, goodneeded = 512;
  356.  
  357.    /* Figure out max data packet size to send */
  358.    maxblklen = KSIZE;
  359.    if (v->Rxbuflen && maxblklen > v->Rxbuflen)
  360.       maxblklen = v->Rxbuflen;
  361.    blklen = (v->Baud < 1200) ? 256 : KSIZE;
  362.    if (blklen > maxblklen)
  363.       blklen = maxblklen;
  364. #ifdef DEBUGLOG
  365.    mysprintf(v->Msgbuf, "Rxbuflen=%ld blklen=%ld\n", (long) v->Rxbuflen,
  366.       (long) blklen);
  367.    dlog(v, v->Msgbuf);
  368. #endif
  369.  
  370.    /* If an interruption happened, handle it; else keep sending data */
  371. somemore:
  372.    while (char_avail(v))
  373.    {
  374.       /* Check for another incoming packet while discarding line noise */
  375.       switch (readock(v, 1))
  376.       {
  377.       case CAN:
  378.       case RCDO:
  379.       case ZPAD:
  380.          break;
  381.       default:
  382.          continue;
  383.          }
  384. waitack:
  385. #ifdef DEBUGLOG
  386.       dlog(v, "--- At waitack\n");
  387. #endif
  388.       switch (c = getinsync(v))
  389.       {
  390.       default:
  391.          upderr(v, "Transfer cancelled");
  392.          bfclose(v);
  393.          return ERROR;
  394.       case ZSKIP:  /* Receiver changed its mind and wants to skip the file */
  395.          return c;
  396.       case ZACK:   /* ACK at end of frame; resume sending data */
  397.          break;
  398.       case ZRPOS:  /* An error; resend data from last good point */
  399.          blklen >>= 2;
  400.          if (blklen < MINBLOCK)
  401.         blklen = MINBLOCK;
  402.          if (goodneeded < MAXGOODNEEDED)
  403.         goodneeded <<= 1;
  404.          v->xpru.xpru_updatemask = XPRU_ERRORS;
  405.          ++v->xpru.xpru_errors;
  406.          (*v->io.xpr_update)(&v->xpru);
  407.          break;
  408.       case ZRINIT:
  409.          updmsg(v, "Done.");
  410.          return OK;
  411.          }
  412.       }
  413.  
  414.    /* Transmit ZDATA frame header */
  415.    framelen = v->Rxbuflen;
  416.    stohdr(v, v->Txpos);
  417.    zsbhdr(v, ZDATA);
  418.  
  419.    /* Keep sending data packets until finished or interrupted */
  420.    do
  421.    {
  422.       /* Read next chunk of file data */
  423.       c = bfread(v, v->Pktbuf, (long) blklen);
  424.  
  425.       /* Figure out how to handle this data packet */
  426.       if (c < blklen)
  427.          e = ZCRCE;  /* If end of file, this is last data packet */
  428.       else if (v->Rxbuflen && (framelen -= c) <= 0)
  429.          e = ZCRCW;  /* If end of frame, ask for ACK */
  430.       else
  431.          e = ZCRCG;  /* Else tell receiver to expect more data packets */
  432.  
  433.       zsdata(v, c, e);  /* Send the packet */
  434.       sendbuf(v);
  435.  
  436.       /* Update comm program status display */
  437.       v->xpru.xpru_updatemask = XPRU_BLOCKS | XPRU_BLOCKSIZE | XPRU_BYTES
  438.          | XPRU_EXPECTTIME | XPRU_ELAPSEDTIME | XPRU_DATARATE
  439.      | XPRU_BLOCKCHECK;
  440.       ++v->xpru.xpru_blocks;
  441.       v->xpru.xpru_blocksize = c;
  442.       v->xpru.xpru_blockcheck = v->Crc32t ? "CRC-32" : "CRC-16";
  443.       v->xpru.xpru_bytes = v->Txpos += c;
  444.       update_rate(v);
  445.       (*v->io.xpr_update)(&v->xpru);
  446.  
  447.       /*
  448.        * If we've been sending smaller than normal packets, see if it's
  449.        * time to bump the packet size up a notch yet
  450.        */
  451.       if (blklen < maxblklen && (goodbytes += c) >= goodneeded)
  452.       {
  453.          blklen <<= 1;
  454.          if (blklen > maxblklen)
  455.         blklen = maxblklen;
  456.          goodbytes = 0;
  457. #ifdef DEBUGLOG
  458.          mysprintf(v->Msgbuf, "Bumping packet size to %ld at %ld\n",
  459.         (long) blklen, v->Txpos);
  460.          dlog(v, v->Msgbuf);
  461. #endif
  462.          }
  463.  
  464.       /* Give comm program its timeslice if it needs one */
  465.       if (v->io.xpr_chkmisc)
  466.      (*v->io.xpr_chkmisc)();
  467.       /* Check for abort from comm program */
  468.       if (v->io.xpr_chkabort && (*v->io.xpr_chkabort)())
  469.      goto aborted;
  470.       /* If this was last packet in frame, go wait for ACK from receiver */
  471.       if (e == ZCRCW)
  472.      goto waitack;
  473.  
  474.       /*
  475.        * Check if receiver trying to interrupt us; look for incoming packet
  476.        * while discarding line noise
  477.        */
  478.       while (char_avail(v))
  479.       {
  480.          switch (readock(v, 1))
  481.      {
  482.          case CAN:
  483.          case RCDO:
  484.          case ZPAD:
  485.             /* Interruption detected; stop sending and process complaint */
  486. #ifdef DEBUGLOG
  487.             dlog(v, "--- Interrupted send\n");
  488. #endif
  489.             zsdata(v, 0, ZCRCE);
  490.             sendbuf(v);
  491.             goto waitack;
  492.             }
  493.          }
  494.       }
  495.    while (e == ZCRCG);  /* If no interruption, keep sending data packets */
  496.  
  497.    /* Done sending file data; send EOF and wait for receiver to acknowledge */
  498.    while (TRUE)
  499.    {
  500.       updmsg(v, "Sending EOF");
  501.       stohdr(v, v->Txpos);
  502.       zsbhdr(v, ZEOF);
  503.       sendbuf(v);
  504.       switch (c = getinsync(v))
  505.       {
  506.       case ZACK:
  507.          continue;
  508.       case ZRPOS:
  509.          goto somemore;
  510.       case ZRINIT:
  511.          updmsg(v, "EOF acknowledged");
  512.          ++v->Starttime.tv_secs;
  513.          update_rate(v);
  514.          v->xpru.xpru_updatemask = XPRU_EXPECTTIME | XPRU_ELAPSEDTIME
  515.         | XPRU_DATARATE;
  516.          (*v->io.xpr_update)(&v->xpru);
  517.          return OK;
  518.       case ZSKIP:
  519.          return c;
  520.       default:
  521. aborted:
  522.      upderr(v, "Transfer cancelled");
  523.          bfclose(v);
  524.          return ERROR;
  525.          }
  526.       }
  527.    }    /* End of short zsendfdata() */
  528.  
  529. /**********************************************************
  530.  *    short getinsync(struct Vars *v)
  531.  *
  532.  * Respond to receiver's complaint, get back in sync with
  533.  * receiver
  534.  **********************************************************/
  535. short getinsync(struct Vars *v)
  536. {
  537.    short c;
  538.  
  539.    while (TRUE)
  540.    {
  541. #ifdef DEBUGLOG
  542.       dlog(v, "--- At getinsync\n");
  543. #endif
  544.       c = zgethdr(v);
  545.       if (v->io.xpr_sflush)
  546.          (*v->io.xpr_sflush)();
  547.       v->Modemcount = 0;
  548.       switch (c)
  549.       {
  550.       case ZCAN:
  551.       case ZABORT:
  552.       case ZFIN:
  553.       case RCDO:
  554.       case TIMEOUT:
  555.          upderr(v, v->Msgbuf);
  556.          return ERROR;
  557.       case ZRPOS:
  558.          bfseek(v, v->Rxpos);
  559.          v->Txpos = v->Rxpos;
  560.          mysprintf(v->Msgbuf, "Resending from %ld", v->Txpos);
  561.          upderr(v, v->Msgbuf);
  562.          return c;
  563.       case ZSKIP:
  564.          upderr(v, "SKIP command received");
  565.          /* fallthrough... */
  566.       case ZRINIT:
  567.          bfclose(v);
  568.          /* fallthrough... */
  569.       case ZACK:
  570.          return c;
  571.       default:
  572.          zsbhdr(v, ZNAK);
  573.          sendbuf(v);
  574.          continue;
  575.          }
  576.       }
  577.    }    /* End of short getinsync() */
  578.  
  579. /**********************************************************
  580.  *    void saybibi(struct Vars *v)
  581.  *
  582.  * End of batch transmission; disengage cleanly from receiver
  583.  **********************************************************/
  584. void saybibi(struct Vars *v)
  585. {
  586.    while (TRUE)
  587.    {
  588.       stohdr(v, 0L);
  589.       zsbhdr(v, ZFIN);
  590.       sendbuf(v);
  591.       switch (zgethdr(v))
  592.       {
  593.       case ZFIN:
  594.          sendline(v, 'O');
  595.          sendline(v, 'O');
  596.          sendbuf(v);
  597.          /* fallthrough... */
  598.       case ZCAN:
  599.       case RCDO:
  600.       case TIMEOUT:
  601.          return;
  602.          }
  603.       }
  604.    }    /* End of void saybibi() */
  605. /* End of Send.c source */
  606.